#include "stm32f10x.h"
#include "string.h"

#include "board.h"



// ------------ Config on USART 3 -----------------
static void initGpioUART3(void) {
    GPIO_InitTypeDef st_g;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    // ===== Config GPIO =====
    // PB10 - USART3_TX, PB11 - USART3_RX
    st_g.GPIO_Pin = GPIO_Pin_10;
    st_g.GPIO_Mode = GPIO_Mode_AF_PP;
    st_g.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &st_g);
    
    st_g.GPIO_Pin = GPIO_Pin_11;
    st_g.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &st_g);
}


static void initUART3(void) {
    USART_InitTypeDef st_u;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    
//    st_u.USART_BaudRate = 19200;  // max baud
    st_u.USART_BaudRate = 9600;
    st_u.USART_WordLength = USART_WordLength_8b;
    st_u.USART_StopBits = USART_StopBits_1;
    st_u.USART_Parity = USART_Parity_No;
    st_u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    st_u.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART3, &st_u);
    
    // ----- do some enable -----
    USART_Cmd(USART3, ENABLE);
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
}


// config interrupt of UART3
static void initUART3IT(void) {
    NVIC_InitTypeDef _st_nvic;
    
//    _st_nvic.NVIC_IRQChannel = USART3_IRQn;
    _st_nvic.NVIC_IRQChannelCmd = ENABLE;
    _st_nvic.NVIC_IRQChannelPreemptionPriority = 0;
    _st_nvic.NVIC_IRQChannelSubPriority = 0;
    
    NVIC_Init(&_st_nvic);
}


//void USART3_IRQHandler(void) {
//    FlagStatus _fg_rxne;
//    char _ch;
//    uint32_t _reg = USART3->SR;
//    
//    _fg_rxne = USART_GetFlagStatus(USART3, USART_FLAG_RXNE);
//    
//    if (SET == _fg_rxne) {    
////    if (SET == USART_GetFlagStatus(USART3, USART_FLAG_RXNE)) {
//        _ch = USART_ReceiveData(USART3);
//        _fg_rxne = _ch;
//    }
//}


// ---------- Simple utilities of USART3 ---------
static void USART_SendByte(const uint8_t b) {
    USART_SendData(USART_MB, b);
    
    while (USART_GetFlagStatus(USART_MB, USART_FLAG_TC) != SET);
}

/**
 @brief Send an array of bytes
 @param bytes the bytes to be sent
 @param n the quantity of bytes to send

 */
static void USART_SendBytes(const char bytes[], int16_t n) {
    if (0 == n) {
        n = strlen(bytes);
    }
    
    for (int16_t i=0; i<n; i++) {
        USART_SendByte(bytes[i]);
    }
}


// ---------- Port for Freemodbus ---------------
#include "mb.h"
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) {
    return MB_ENOREG;
}

//eMBErrorCode
//eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
//                 eMBRegisterMode eMode )
//{
//    for (uint16_t i=0; i<usNRegs; i++) {
//        pucRegBuffer[i*2 + 1] = i + 0x42;
//    }
//    return MB_ENOERR;
//}


eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
               eMBRegisterMode eMode )
{
    return MB_ENOREG;
}

eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    return MB_ENOREG;
}


// ---------- demos to test the features --------

static void delay(void) {
    for(uint32_t t=0xFFFFF; t>0; t--) {}    
}


void demo_uart3(void) {
    initGpioUART3();
    initUART3();
    initUART3IT();
    
    while (1) {
        USART_SendBytes("Hello\r\n", 0);
//        USART3_SendByte(0x33);
        delay();
    }
}


void demo_freemodbus(void) {
    initBoard();
//    initUART3();
    
    // mode, slave addr, port, baud, parity
    eMBInit(MB_RTU, 0x01, 0x00, 9600, MB_PAR_NONE);
    eMBEnable();
//    
//    delay();

//    
    while (1) {
        eMBPoll();
        
//        USART_SendBytes("Hello\r\n", 0);
//        delay();
    }
}


